這篇文章的主題比較瑣碎,我們將一同探討幾個在嵌入式系統中,有關硬體資源配置要留意的細節。
現在要令一個無號整數變數為 0,寫法如下:
unsigned int zero = 0;
這個 0 代表所有位元都是 0,也就是 0000 0000 0000 0000,那如果要寫出它的補數(也就是位元通通反轉),可以怎麼寫呢?
補數不就是 1111 1111 1111 1111,而每個 1111 都是十六進制的 F,那這樣寫不就得了?
unsigned int compzero = 0xFFFF;
看起來很合理,對吧?然而,這是在 16 位元的電腦有效,同樣的 compzero 如果放到 32 位元、甚至 64 位元的電腦上,會變成什麼呢?
32 位元電腦:
0000 0000 0000 0000 1111 1111 1111 1111
= 0x 0 0 0 0 F F F F
64 位元電腦:
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111
= 0x 0 0 0 0 0 0 0 0 0 0 0 0 F F F F
但期待的數值其實是不管多少位元,通通都要變成 1,而不是前面還補上了 0。
直接用指定數量的 F 寫死會導致該數隨電腦位元數不同而改變其代表的值,因此最好的方法應該是直接說要反轉這個 0 的每個位元,如下:
unsigned int compzero = ~0;
這個 compzero 不管放在多少位元的電腦上,都代表 0 的補數,也就是每個位元都是 1。
在嵌入式系統中,偶有從堆積(heap)中動態分發記憶體的可能,但這些操作可能引發下列三種問題:
包含「外碎片(external fragmentation)」與「內碎片(internal fragmentation)」。
外碎片指的是空閒的記憶體零碎而不連續,例如以下記憶體空間:
已被佔用打 X: XX XXX X XX
記憶體空間 :____ ____ ____ ____
上面的記憶體空間共有 16 個單位、其中 8 個被佔用,表面上還有另外 8 個單位可以用。
然而,如果有某項工作要求配置 5 個單位的連續的記憶體空間,在這個範例中是找不到對應資源的,因為連續的空閒記憶體最長只有 3 個單位。
內碎片指的是已被使用的記憶體空間浪費,例如系統為某項工作配置 4 個單位的記憶體空間,但實際上只要用到 1 單位,那多出來的 3 個單位就是內碎片。
V <- 實際上只用到一個單位,剩下三個浪費掉的稱為內碎片
____ <- 一共配置四個單位的記憶體空間給某項工作
講的是給某變數用 malloc() 配置記憶體空間後,未在使用完畢、不再需要用到該變數時用 free() 把記憶體空間釋放出來,造成可用的記憶體空間逐漸減少,稱為「記憶體洩漏(memory leak)」問題。
在比較高階的語言會有「垃圾回收」機制,由系統自己尋找不再使用的變數、把其佔據的空間收回來。
這樣做的好處是不用手動做 free(),但垃圾回收時機並不可測,可能導致短暫的停頓或延遲,造成系統不穩定。例如無人機飛行時,如果在某個不可預期的時間點進行垃圾回收,就會有一小段時間出現無人機無法處理飛行任務,造成飛行不穩定、甚至墜毀。